from flask_restful import Resource
from comment.models.user import User
from flask import current_app, request,g
from comment.utils.python_sms_sdk_master.example.SendMessage import send_message
import random
import json
from comment.utils.limiter import limiter as lmt
from . import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from comment.models import db
from comment.utils.tockens_pyjwt import generate_tokens
from comment.utils.decorators import login_required



# 我们定义测试的资源类
class Shopping_User(Resource):
    # 在get函数上加上登陆的拦截
    method_decorators = {
        'get': [login_required],
        'post': [login_required]
    }

    # 这里的代码会用到User模型类
    def get(self): # 测试:当前get函数必须让用户登陆之后才能访问
        current_app.logger.info('我的测试日志')
        return {"hello": "get测试"}

    def post(self):
        return {'post':'post测试'}

    def put(self):
        return {'put':'put测试'}


class User_SMS(Resource):
    """
    发送验证码的短信，
    """
    error_message = '发送短信太多了.'
    decorators = [
        # 三个参数，参数1，限流器，限流的速率。参数2:key_func,参数3:如果超出限制之后的提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=lambda: request.args['phone'],
                  error_message=error_message),
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=get_remote_address,  # 客户端远程IP地址
                  error_message=error_message)
    ]

    def get(self):
        mobile = request.args.get("phone").strip()
        code = random.randint(100000, 999999)
        result = send_message(mobile, str(code))  # 返回的是json的字符串
        result = json.loads(result)  # 把json变成字典
        # result 往里面添加手机号
        result['mobile'] = mobile
        key = 'shopping:code{}'.format(mobile)
        # 短信验证码发送成功后，需要把验证码存放到redis数据库中,方便下次验证,验证码的时效为5分钟
        redis_client.setex(key, constants.SMS_CODE_EXPIRES, code)  # 参数1key,参数2时间

        return result


class AuthorizationCodeResource(Resource):
    """
    提交手机号和验证码，开始验证
    """

    def post(self):
        rp = RequestParser()
        # mobile 手机号
        rp.add_argument('phone', type=parser.mobile,location='form', required=True)  # 只是一个函数不能调用
        rp.add_argument('code', type=parser.regex(r'^\d{6}$'),location='form', required=True) # 4==6 # 验证码是6位的
        ages = rp.parse_args()
        mobile = ages.phone
        code = ages.code

        # 从redis数据库中得到之前保存的验证码
        # key = 'shopping:code:{}'.format(mobile) # 多了一个冒号
        key = 'shopping:code{}'.format(mobile)
        try:
            real_code = redis_client.get(key)  # 从redis中返回的是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'message': 'redis db connect error.'}, 400

        # 开始校验
        if not real_code or real_code.decode() != code:
            return {'message': 'Invalid code.'}, 400

        return {'mobile': mobile, 'msg': 'code success'}


class RegisterUserResource(Resource):
    """
    填写账号信息:完成用户的注册
    """

    # @property
    def post(self):
        rp = RequestParser()
        # rp.add_argument('mobile',, required=True)  # 只是一个函数不能调用
        rp.add_argument('phone', type=parser.mobile, required=True)  # 只是一个函数不能调用 # 这是改动后的
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        # rp.add_argument('emaie', type=parser.email, required=True)
        rp.add_argument('email', type=parser.email, required=True)
        ages = rp.parse_args()
        username = ages.username
        password = ages.password
        mobile = ages.phone
        email = ages.email

        # 验证用户名是否唯一: 先从mysql数据库中根据当前用户名查询
        u = User.query.filter(User.username == username).first()
        if u:  # 用户名已经存在
            current_app.logger.info('{}:用户名已经存在'.format(username))
            return {'message': 'The username already exists.'}, 400

        # 把用户信息保存到数据库
        u = User(username=username, pwd=password, phone=mobile, email=email, status=0)
        db.session.add(u)
        db.session.commit()
        return {'msg': 'ok'}


class UserLoginResource(Resource):
    """
    登陆 后端登陆验证我就不写了前端界面做验证
    """

    def post(self):
        username = request.form.get('username') # 这是表单提交
        password = request.form.get('password')

        if not all([username, password]):
            return {'message': '数据不完整'}, 401

        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                # 必须把登陆成功之后用户得到的token，把token返回给前端
                token = generate_tokens(user.id)
                return {'msg': 'Login Success', 'token': token, 'username': username}, 200
        return {'message': '用户名或者密码错误'}, 400

class UserLoginOutResource(Resource):
    """
    退出登陆
    """
    def post(self):
        if g.user_id:
            g.user_id = None
        return {'msg':'退出登陆！成功'}


# 这三种都是加密算法
# SHA526 分为 SHA1 SHA2
# MD5
# HASH 可逆的算法

class IsExistPhoneResource(Resource):
    """
    判断手机号是否存在
    """
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone == phone).first()
        if user: # 如果用户有，则表示手机号存在
            return {'isExist': True, 'massage': '此手机已经注册', 'code': 203}
        return {'msg':'手机号可以注册'}






